/*
 *所有关于PhysicalStock类的业务代码应在此处编写
*可使用repository.调用常用方法，获取EF/Dapper等信息
*如果需要事务请使用repository.DbContextBeginTransaction
*也可使用DBServerProvider.手动获取数据库相关信息
*用户信息、权限、角色等使用UserContext.Current操作
*PhysicalStockService对增、删、改查、导入、导出、审核业务代码扩展参照ServiceFunFilter
*/
using VOL.Core.BaseProvider;
using VOL.Core.Extensions.AutofacManager;
using VOL.Entity.DomainModels;
using System.Linq;
using VOL.Core.Utilities;
using System.Linq.Expressions;
using VOL.Core.Extensions;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Http;
using VOL.Domain.IRepositories;
using SkiaSharp;
using VOL.Domain.Dto;
using VOL.Domain.Infrastructure;
using VoL.Domain.Infrastructure;
using VOL.Domain.IServices;
using System.Threading.Tasks;
using System.Collections.Generic;

namespace VOL.Domain.Services
{
    public partial class PhysicalStockService
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IBaseRepository<PhysicalStock> baseRepository;
        private readonly IPhysicalStockRepository _repository;

        [ActivatorUtilitiesConstructor]
        public PhysicalStockService(
            IPhysicalStockRepository dbRepository,
            IHttpContextAccessor httpContextAccessor,
            IBaseRepository<PhysicalStock> baseRepository
            )
        : base(dbRepository)
        {
            _httpContextAccessor = httpContextAccessor;
            this.baseRepository = baseRepository;
            _repository = dbRepository;
        }

        public async Task<List<MenuItemDto>> GetMenuTreeAsync()
        {
            var all = baseRepository.GetAll().ToList();

            List<MenuItemDto> BuildTree(int? parentId)
            {
                return (all
                    .Where(x => x.ParentId == parentId)
                    .Select(x => new MenuItemDto
                    {
                        Id = x.Id,                    
                        Label = x.MaterialName,
                        MaterialCode=x.MaterialCode,
                        ParentId = x.ParentId,
                        Children = BuildTree(x.Id)
                    })).DistinctBy(x => x.MaterialCode)
                    .ToList();
            }

            return BuildTree(0);
        }

        public async Task<PagedResponseDto<PhysicalStock>> SearchAsync(PhysicalStockSearchDto searchDto)
        {
            var query = baseRepository.GetAll();

            // Apply filters
            if (!string.IsNullOrEmpty(searchDto.MaterialCode))
                query = query.Where(x => x.MaterialCode.Equals(searchDto.MaterialCode));

            if (!string.IsNullOrEmpty(searchDto.MaterialName))
                query = query.Where(x => x.MaterialName.Contains(searchDto.MaterialName));

            if (!string.IsNullOrEmpty(searchDto.BatchNo))
                query = query.Where(x => x.LotNum.Contains(searchDto.BatchNo));

            if (!string.IsNullOrEmpty(searchDto.WarehouseName))
                query = query.Where(x => x.Depot.Contains(searchDto.WarehouseName));

            if (!string.IsNullOrEmpty(searchDto.WarehouseCode))
                query = query.Where(x => x.Depot.Contains(searchDto.WarehouseCode));

            if (!string.IsNullOrEmpty(searchDto.LocationName))
                query = query.Where(x => x.BinLocation.Contains(searchDto.LocationName));

            if (!string.IsNullOrEmpty(searchDto.LocationCode))
                query = query.Where(x => x.BinLocation.Contains(searchDto.LocationCode));

            if (searchDto.IsFrozen.HasValue)
                query = query.Where(x => x.Status == (searchDto.IsFrozen.Value ? 1 : 0));

            if (!string.IsNullOrEmpty(searchDto.StorageName))
                query = query.Where(x => x.GalleryArea.Contains(searchDto.StorageName));

            // Get total count
            var totalCount = await query.CountAsync();

            // Apply pagination
            var items = await query
                .Skip((searchDto.Page - 1) * searchDto.PageSize)
                .Take(searchDto.PageSize)
                .ToListAsync();

            return new PagedResponseDto<PhysicalStock>
            {
                Data = items,
                TotalCount = totalCount,
                CurrentPage = searchDto.Page,
                PageSize = searchDto.PageSize,
                TotalPages = (int)Math.Ceiling(totalCount / (double)searchDto.PageSize)
            };
        }
    }
}
